#include "common.h"

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <stdint.h>
#include <string.h>
#include <stdarg.h>
 
#define OFFSET_YEAR 1900
#define SCALE_MS2NS 1000000

static char *g_logLevel[LOG_LEVEL_BUTT] = {
    "TRACE",
    "DEBUG",
    "INFO",
    "WARN",
    "ERROR",
    "FATAL"
};

int32_t Logf(enum LogLevel level, const char *format, ...)
{
    if (level < TRACE || level >= LOG_LEVEL_BUTT) {
        return -1;
    }
    char *levelTag = g_logLevel[level];

    struct timespec spec;
    clock_gettime(CLOCK_REALTIME, &spec);
    struct tm *t = localtime(&spec.tv_sec);
    static size_t timestamp = sizeof("1900-01-01 00:00:00.000");
    static size_t split = sizeof(" - ");
    // log format: 1900-01-01 00:00:00.000 INFO - this is a sample log\n\0
    char *logFormat = calloc(timestamp + 1 + strlen(levelTag)+ split + strlen(format) + 1 + 1, sizeof(char));
    if (logFormat == NULL) {
        return -1;
    }
    sprintf(logFormat, "%04d-%02d-%02d %02d:%02d:%02d.%03ld %s - %s\n", t->tm_year + OFFSET_YEAR, t->tm_mon + 1, t->tm_mday,
            t->tm_hour, t->tm_min, t->tm_sec, spec.tv_nsec / SCALE_MS2NS, levelTag, format);

    va_list args;
    va_start(args, format);
    int ret = vprintf(logFormat, args);
    va_end(args);
    free(logFormat);

    if (level == FATAL) {
        exit(1);
    }

    return ret;
}